/*
============================================================================
 Name        : PdImageDecoder.cpp
 Author      : Jian(raphyer@hotmail.com)
 Version     :
 Copyright   : GPL
 Description : CPdImageDecoder implementation
============================================================================
*/

#include "PdImageDecoder.h"
#include "PdDefine.h"

#include <ImageConversion.h>
#include <BitmapTransforms.h>


CPdImageDecoder::CPdImageDecoder() : 
CActive(EPriorityStandard), iDecodeFinish(EFalse)
{
}

CPdImageDecoder::~CPdImageDecoder()
{
    Cancel(); 

    __doDelete(iImageDecoder) ;
    __doDelete(iScaler) ;
    __doDelete(iBitmap) ;
    __doDelete(iMask) ;
    __doDelete(iDecodeData) ;

    iFs.Close() ;
}

CPdImageDecoder* CPdImageDecoder::NewL(const TDesC& aFileName, const TSize& aSize) 
{
    CPdImageDecoder* self = new(ELeave) CPdImageDecoder() ;
    CleanupStack::PushL(self) ;

    TRAPD(err, self->_doInit(aFileName, aSize);) ; 

    if (err != KErrNone) 
        DD_LOG("CPdImageDecoder Try to decode a file error = %d", &aFileName, err) ;

    CleanupStack::Pop(self) ;
    return self ;
}

CPdImageDecoder* CPdImageDecoder::NewDataL(HBufC8* aImageData, const TSize& aSize) 
{
    CPdImageDecoder* self = new(ELeave) CPdImageDecoder() ;
    CleanupStack::PushL(self) ;

    TRAPD(err, self->_doInitData(aImageData, aSize);) ; 

    if (err != KErrNone) 
        DD_LOG("CPdImageDecoder Try to decode data error = %d", err) ;

    CleanupStack::Pop(self) ;
    return self ;
}


void CPdImageDecoder::_doInit(const TDesC& aFileName, const TSize& aSize)
{
    CActiveScheduler::Add(this);

    iState = EDecoding ;

    iImageSize = aSize ;

    LogLeaveIfError(iFs.Connect()) ;

    LogLeaveIfNull(iImageDecoder = CImageDecoder::FileNewL(iFs, aFileName));

    LogLeaveIfNull(iBitmap = new (ELeave) CFbsBitmap());

    LogLeaveIfNull(iMask = new (ELeave) CFbsBitmap());

    LogLeaveIfError(iBitmap->Create(iImageDecoder->FrameInfo().iOverallSizeInPixels, iImageDecoder->FrameInfo().iFrameDisplayMode)) ;

    LogLeaveIfError(iMask->Create(iImageDecoder->FrameInfo().iOverallSizeInPixels, EGray256));

    iImageDecoder->Convert(&iStatus, *iBitmap, *iMask) ;

    SetActive();
}


void CPdImageDecoder::_doInitData(HBufC8* aImageData, const TSize& aSize)
{
    CActiveScheduler::Add(this);

    iState = EDecoding ;

    iImageSize = aSize ;

    iDecodeData = aImageData ;

    LogLeaveIfError(iFs.Connect()) ;

    LogLeaveIfNull(iImageDecoder = CImageDecoder::DataNewL(iFs, *iDecodeData));

    LogLeaveIfNull(iBitmap = new (ELeave) CFbsBitmap());

    LogLeaveIfNull(iMask = new (ELeave) CFbsBitmap());

    LogLeaveIfError(iBitmap->Create(iImageDecoder->FrameInfo().iOverallSizeInPixels, iImageDecoder->FrameInfo().iFrameDisplayMode)) ;

    LogLeaveIfError(iMask->Create(iImageDecoder->FrameInfo().iOverallSizeInPixels, EGray256));

    iImageDecoder->Convert(&iStatus, *iBitmap, *iMask) ;

    SetActive();
}


void CPdImageDecoder::DoCancel()
{
    if (iImageDecoder)
        iImageDecoder->Cancel();

    if (iScaler)
        iScaler->Cancel() ;
}


void CPdImageDecoder::RunL()
{
    if (iStatus.Int() == KErrNone) {
        if (iState == EDecoding) {
            __doDelete(iImageDecoder) ;
            __doDelete(iDecodeData) ;

            if (iImageSize == iBitmap->SizeInPixels()) {
                iDecodeFinish = ETrue ;
                return ;
            }

            iState = EScaleBitmap;

            iScaler = CBitmapScaler::NewL();
            iScaler->Scale(&iStatus, *iBitmap, iImageSize);

            SetActive();
        } else if (iState == EScaleBitmap) {
            if (iMask) {
                iState = EScaleMask;

                iScaler->Scale(&iStatus, *iMask, iImageSize);
                SetActive();
            }
            else {
                iDecodeFinish = ETrue ;
            }
        } else if (iState == EScaleMask) {
            iDecodeFinish = ETrue ;
        }

        return ;
    }

    DD_LOG("CPdImageDecoder error, current state = %d and error code = %d", iState, iStatus.Int()) ;

}


/* End of File */
